<?php

class PostgreSQLQuery extends AFQueriable
{
	const AFCreate = 0;
	const AFAlter = 1;
	const AFDrop = 2;
	const AFSelect = 3;
	const AFUpdate = 4;
	const AFDelete = 5;

	public $owner = NULL;
	public $type = self::AFCreate;

	public function execute($query)
	{
		$this->owner->query($query);
		return $this->owner;
	}
}

class PostgreSQLField extends AFQueriable {
	public $name;
	public $type;
	public $isNotNull = FALSE;
//	public $
}

class PostgreSQLCreate extends PostgreSQLQuery
{
	public $name;
	public $fields;

	public function go()
	{
		$this->type = self::AFCreate;
		return parent::execute("CREATE $this->what $this->fields");
	}
}

class PostgreSQLSelect extends PostgreSQLQuery
{
	public $what = '*';
	public $from;
	public $where = 'TRUE';
	public $orderBy = '1';
	public $limit = '1000';

	public function go()
	{
		$this->type = self::AFSelect;
		return parent::execute("SELECT $this->what FROM $this->from WHERE $this->where ORDER BY $this->orderBy LIMIT $this->limit");
	}
}

class PostgreSQL
{
	private $host = 'localhost';
	private $port = 5432;
	private $user = '';
	private $password = '';
	private $database = '';

	private $conn = NULL;
	private $result = NULL;

	private $tables = array();

	private $plan = NULL;

	public function connect(/* host, user, password, database, port */)
	{
		if(func_num_args() > 0)
		{
			$this->host = func_get_arg(0);
		}
		if(func_num_args() > 1)
		{
			$this->user = func_get_arg(1);
		}
		if(func_num_args() > 2)
		{
			$this->password = func_get_arg(2);
		}
		if(func_num_args() > 3)
		{
			$this->database = func_get_arg(3);
		}
		if(func_num_args() > 4)
		{
			$this->port = func_get_arg(4);
		}

		$this->conn = @pg_connect(sprintf('host=%s port=%d user=%s password=%s dbname=%s ', $this->host, $this->port, $this->user, $this->password, $this->database));
		if(!$this->conn)
		{
			throw new AFSQLException('Failed to connect to host '.$this->host.' on port '.$this->port, 2);
		}

		$this->tables = $this->query('SELECT schemaname AS schema, tablename AS name FROM pg_tables WHERE schemaname <> \'pg_catalog\' AND schemaname <> \'information_schema\';')->getObjects();

		return $this;
	}

	public function query($query)
	{
		$this->result = pg_query($this->conn, $query);
		return $this;
	}

	public function getValue()
	{
		$result = pg_fetch_assoc($this->result);
		if($result)
		{
			return $result[0];
		}
		return NULL;
	}

	public function getObject()
	{
		$result = pg_fetch_assoc($this->result);
		if($result)
		{
			return (object)$result;
		}
		return NULL;
	}

	public function getObjects()
	{
		$objects = array();
		while($object = $this->getObject())
		{
			$objects[] = $object;
		}
		return $objects;
	}
	public function getLastError()
	{
		return pg_last_error($this->conn);
	}

	public function getRowCount()
	{
		return pg_num_rows($this->result);
	}

	public function getFieldCount()
	{
		return pg_num_fields($this->result);
	}

	public function getModifiedCount()
	{
		return pg_affected_rows($this->result);
	}

	public function disconnect()
	{
		return pg_close($this->conn);
	}

	public function getTablesList()
	{
		return $this->tables;
	}

	public function hasTable()
	{
	}

	public function select($what = '*')
	{
		$this->plan = new PostgreSQLSelect();
		$this->plan->what($what);
		$this->plan->owner($this);
		return $this->plan;
	}

	public function create($name)
	{
		$this->plan = new PostgreSQLCreate();
		$this->plan->owner($this);
		$this->plan->name($name);
		return $this->plan;
	}
}

?>
